<?php
/**
 * @package qBase
 * @subpackage sql
 *
 */

/**
 * The QSqlTableIndex represents an abstract database index
 * 
 * @package qBase
 * @subpackage sql
 */
class QSqlTableIndex extends QObject implements QIAllowSerialize 
{	
	/**
	 * The Primary Key index type
	 *
	 */
	const IndexPrimary = 1;
	/**
	 * The unique index type
	 *
	 */
	const IndexUnique = 2;
	/**
	 * Simple index type
	 *
	 */
	const IndexNormal = 3;
	/**
	 * Full text index type
	 *
	 */
	const IndexFullText = 4;
	/**
	 * The type of the index as defined by the QSqlTableIndex constants
	 *
	 * @var integer
	 */
	public $type;
	/**
	 * The name of the index
	 *
	 * @var string
	 */
	public $name;
	/**
	 * The new name of the index (in case of a rename)
	 *
	 * @var string
	 */
	public $new_name;
	/**
	 * The list of fields that compose the index
	 *
	 * @var array
	 */
	public $fields;
	/**
	 * The table where the index exists
	 *
	 * @var QSqlTable
	 */
	public $table;
	/**
	 * If the index is foreign key it points to another index. The other index should have the same number of fields and of similar types.
	 *
	 * @var QSqlTableIndex
	 */
	public $foreign_key;

	/**
	 * The constructor of QSqlTableIndex
	 *
	 * @param QSqlTable $table The table where the index exists
	 * @param integer $type The type of the index as defined by the QSqlTableIndex constants
	 * @param string $name The name of the index
	 * @param array $fields The list of fields that compose the index
	 * @param QSqlTableIndex $foreign_key
	 */
	public function __construct($table = null, $type = null, $name = null, $fields = null, $foreign_key = null)
	{
		$this->table = $table;
		$this->type = $type;
		$this->name = $name;
		if ($fields)
		{
			foreach ($fields as $f)
				if (!$f)
					throw new Exception("A field can not be null");
			$this->fields = $fields;
		}
		$this->foreign_key = $foreign_key;
	}
	
	/**
	 * Gets the table of the index
	 *
	 * @return QSqlTable
	 */
	public function getTable()
	{
		return $this->table;
	}
	
	/**
	 * Sets the table of the index
	 *
	 * @param QSqlTable $table
	 */
	public function setTable(QSqlTable $table)
	{
		$this->table = $table;
	}
	
	/**
	 * Gets the type of the index
	 *
	 * @return integer
	 */
	public function getType()
	{
		return $this->type;
	}
	
	/**
	 * Sets the type of the index
	 * Changes only apply on the database server after calling "updateIndex"
	 *
	 * @param integer $type
	 */
	public function setType($type)
	{
		$this->type = $type;
	}
	
	/**
	 * Gets the name of the index
	 *
	 * @return string
	 */
	public function getName()
	{
		if ($this->new_name)
			return $this->new_name;
		else 
			return $this->name;
	}
	
	/**
	 * Sets the name of the index
	 * Changes only apply on the database server after calling "updateIndex"
	 *
	 * @param string $name
	 * @param boolean $is_new_name If is new name , then the "new_name" variable is set instead of name so that on "updateIndex" we will know the old name of the index
	 */
	public function setName($name, $is_new_name = true)
	{
		if ($is_new_name)
			$this->new_name = $name;
		else 
			$this->name = $name;
	}
	
	/**
	 * Gets the new name of the index (in case of a rename)
	 *
	 * @return string
	 */
	public function getNewName()
	{
		return $this->new_name;
	}
	
	/**
	 * Gets the old name of the index (in case of a rename)
	 *
	 * @return string
	 */
	public function getOldName()
	{
		if ($this->new_name)
			return $this->name;
		else 
			return null;
	}
	
	/**
	 * Gets the fields of the index
	 *
	 * @return array
	 */
	public function getFields()
	{
		return $this->fields;
	}
	
	public function getFieldsCount()
	{
		if (isset($this->fields) && is_array($this->fields))
			return count($this->fields);
		else 
			return 0;
	}
	
	/**
	 * Gets the field at the specified position in the index
	 *
	 * @param integer $position
	 * @return QSqlTableField
	 */
	public function getFieldAt($position)
	{
		if (isset($this->fields[$position]))
			return $this->fields[$position];
		else 
			return null;
	}
	
	/**
	 * Gets the number of fields in the index
	 *
	 * @return integer
	 */
	public function countFields()
	{
		if (!$this->fields)
			return 0;
		else 
			return count($this->fields);
	}
	
	/**
	 * Adds a field to the index at the specified position, if the position is ignored the it's added at the end
	 * Changes only apply on the database server after calling "updateIndex"
	 *
	 * @param QSqlTableField $field
	 * @param integer $pos
	 */
	public function addField(QSqlTableField $field, $pos = null)
	{
		if (!$this->fields)
			$this->fields = array();
		if (is_null($pos) || ($this->getFields() >= $pos))
			$this->fields[] = $field;
		else 
			array_splice($this->fields[], $pos, 0, array($field));
	}
	
	/**
	 * Removes a field from the index. Return true if the field has been found and removed
	 * Changes only apply on the database server after calling "updateIndex"
	 *
	 * @param string $field_name
	 * @return boolean
	 */
	public function removeField($field_name)
	{
		$count = $this->countFields();
		for ($i = 0; $i < $count; $i++)
			if ($this->fields[$i]->getName() == $field_name)
			{
				array_splice($this->fields, 0, 1);
				return true;
			}
		return false;
	}
	
	/**
	 * Updates the changes made to this index
	 *
	 */
	public function updateIndex()
	{
		$this->table->updateIndex($this);
		$this->renameDone();
	}
	
	/**
	 * After rename or update we need to reset the state for $new_name
	 *
	 */
	public function renameDone()
	{
		if ($this->new_name)
		{
			$this->name = $this->new_name;
			unset($this->new_name);
		}
	}
	
	/**
	 * Unsets the table pointer
	 *
	 */
	public function unsetTable()
	{
		unset($this->table);
	}
	
	/**
	 * Gets the foreign key index if any is defined
	 *
	 * @return QSqlTableIndex
	 */
	public function getForeignKey()
	{
		return $this->foreign_key;
	}
	
	/**
	 * Sets the foreign key
	 *
	 * @param QSqlTableIndex $foreign_key
	 */
	public function setForeignKey(QSqlTableIndex $foreign_key)
	{
		$this->foreign_key = $foreign_key;
	}
	
	/**
	 * Unsets this foreign key
	 *
	 */
	public function unsetForeignKey()
	{
		unset($this->foreign_key);
	}
}

?>